/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.unbiz.either;

import java.io.Serializable;
import java.util.Map;

import org.apache.commons.collections4.KeyValue;

import com.unbiz.tuple.Tuple2;

/** A simple (ordered) pair of two objects. Elements may be null. */
public final class Pair<A, B> extends Tuple2<A, B> implements Map.Entry<A, B>, KeyValue<A, B>, Cloneable, Serializable {

	public Pair(A _0, B _1) {
		super(_0, _1);
	}

	public A getFirst() {
		return _0;
	}

	public B getSecond() {
		return _1;
	}

	public Pair<B, A> swap() {
		return new Pair<B, A>(_1, _0);
	}

	/*
	 * Pair<Int,String>.of(1,"str")
	 */
	public static <A, B> Pair<A, B> of(A a, B b) {
		return new Pair<A, B>(a, b);
	}

	@Override
	public String toString() {
		return '(' + String.valueOf(_0) + ',' + _1 + ')';
	}

	/**
	 * Defines an ordering on pairs that sorts by _0 value's natural ordering,
	 * ascending, and then by _1 value's natural ordering.
	 *
	 * @throws ClassCastException
	 *             if types are not actually {@link Comparable}
	 */
	@Override
	public int compareTo(Tuple2<A, B> other) {
		Comparable<A> this_0 = (Comparable<A>) _0;
		A that_0 = other._0;
		int compare = this_0.compareTo(that_0);
		if (compare != 0) {
			return compare;
		}
		Comparable<B> this_1 = (Comparable<B>) _1;
		B that_1 = other._1;
		return this_1.compareTo(that_1);
	}

	@Override
	public A getKey() {
		// TODO Auto-generated method stub
		return _0;
	}

	@Override
	public B getValue() {
		// TODO Auto-generated method stub
		return _1;
	}

	@Override
	public B setValue(B value) {
		// TODO Auto-generated method stub
		throw new UnsupportedOperationException();
		// return _1;
	}
}
